home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 38 / Amiga Format CD38 (1999-03-15)(Future Publishing)(GB)(Track 1 of 3)[!][issue 1999-04].iso / -seriously_amiga- / programming / other / cyberxxxsrc / cyberavi / txt / cyberaviaudio.mod < prev    next >
Text File  |  1999-02-08  |  25KB  |  708 lines

  1. MODULE  CyberAVIAudio;
  2.  
  3. (* $IFNOT DEBUG *)
  4.   (* $StackChk- $OvflChk- $RangeChk- $CaseChk- $ReturnChk- $NilChk- $TypeChk- $OddChk- $ClearVars- *)
  5. (* $END *)
  6.  
  7. (* /// ------------------------------- "IMPORT" -------------------------------- *)
  8. IMPORT  au:=Audio,
  9.         aus:=AudioSupport,
  10.         cu:=CyberAVIUtils,
  11.         d:=Dos,
  12.         e:=Exec,
  13.         es:=ExecSupport,
  14.         els:=ExecListSupport,
  15.         g:=CyberAVIGlobals,
  16.         i2m:=Intel2Mot,
  17.         io:=AsyncIOSupport,
  18.         mu:=MathUtils,
  19.         o:=CyberAVIOpts,
  20.         ol:=OberonLib,
  21.         s:=CyberAVISync,
  22.         u:=Utility,
  23.         v:=CyberAVIVideo,
  24.         y:=SYSTEM;
  25. (* \\\ ------------------------------------------------------------------------- *)
  26.  
  27. (* /// -------------------------------- "TYPE" --------------------------------- *)
  28. TYPE    CommonDataPtr=UNTRACED POINTER TO CommonData;
  29.         CommonData=STRUCT
  30.             downScale: BOOLEAN;
  31.         END;
  32.  
  33.  
  34.         CodecHeader=STRUCT
  35.             compression: INTEGER;
  36.             channels: INTEGER;
  37.             bits: INTEGER;
  38.             extSize: INTEGER;
  39.             stereo: BOOLEAN;
  40.             description: e.STRING;
  41.             compFactor: LONGINT;
  42.         END;
  43.  
  44.         ExtendedDataPtr=UNTRACED POINTER TO ExtendedData;
  45.         ExtendedData=STRUCT
  46.         END;
  47.  
  48.         DecoderProc=PROCEDURE(from{8}: e.APTR;
  49.                               toL{9}: e.APTR;
  50.                               toR{10}: e.APTR;
  51.                               size{0}: LONGINT;
  52.                               spec{11}: CommonDataPtr): LONGINT;
  53.  
  54.         SampleNodePtr=UNTRACED POINTER TO SampleNode;
  55.         SampleNode=STRUCT (node: e.MinNode)
  56.             freq: LONGINT;
  57.             dataL: e.LSTRPTR;
  58.             dataR: e.LSTRPTR;
  59.             size: LONGINT;
  60.             done: LONGINT;
  61.             id: LONGINT;
  62.         END;
  63. (* \\\ ------------------------------------------------------------------------- *)
  64.  
  65. (* /// -------------------------------- "CONST" -------------------------------- *)
  66. CONST   waveUnknown=00000H;
  67.         wavePCM=0001H;
  68.         waveMsADPCM=0002H;
  69.         waveIBMCVSD=0005H;
  70.         waveALAW=0006H;
  71.         waveMULAW=0007H;
  72.         waveOkiADPCM=0010H;
  73.         waveDviADPCM=0011H;
  74.         waveDigiStd=0015H;
  75.         waveDigiFix=0016H;
  76.         waveYamahaADPCM=0020H;
  77.         waveDSPTrueSpeech=0022H;
  78.         waveMsGSM610=0031H;
  79.         ibmMULAW=0101H;
  80.         ibmALAW=0102H;
  81.         ibmADPCM=0103H;
  82.  
  83.         codecSupported * =1;
  84.         codecUnknown * =0;
  85.         codecUnsupported * =-1;
  86.  
  87.         maxAudioHWSize=131072;
  88. (* \\\ ------------------------------------------------------------------------- *)
  89.  
  90. (* /// --------------------------------- "VAR" --------------------------------- *)
  91. VAR     mainData: e.LSTRPTR;
  92.         mainPort: e.MsgPortPtr;
  93.         mainIO: au.IOAudioPtr;
  94.         leftData: ARRAY 2 OF e.LSTRPTR;
  95.         leftPort: ARRAY 2 OF e.MsgPortPtr;
  96.         leftIO: ARRAY 2 OF au.IOAudioPtr;
  97.         rightData: ARRAY 2 OF e.LSTRPTR;
  98.         rightPort: ARRAY 2 OF e.MsgPortPtr;
  99.         rightIO: ARRAY 2 OF au.IOAudioPtr;
  100.         audioOpen - : BOOLEAN;
  101.         decoderProc: DecoderProc;
  102.         decoderSpec: CommonDataPtr;
  103.         audioFreq: LONGINT;
  104.         audioBufferSize: LONGINT;
  105.         audioSizeScale: LONGINT;
  106.         currSample: SHORTINT;
  107.         stereo: BOOLEAN;
  108.         playing: BOOLEAN;
  109.         bufPlaying: ARRAY 2 OF BOOLEAN;
  110.         currentRead: LONGINT;
  111.         maxRead: LONGINT;
  112.         totalRead: LONGINT;
  113.         totalAudioSize: LONGINT;
  114.         initFrames: LONGINT;
  115.         extendedData: ExtendedDataPtr;
  116.         sampleQueue: els.Queue;
  117.         audioSigs - :  LONGSET;
  118.         mustPreload * : BOOLEAN;
  119. (* \\\ ------------------------------------------------------------------------- *)
  120.  
  121. (* /// --------------------- "PROCEDURE FlushQueueFunc()" ---------------------- *)
  122. PROCEDURE FlushQueueFunc(n: e.CommonNodePtr);
  123. BEGIN
  124.   DISPOSE(n(SampleNodePtr).dataL);
  125.   DISPOSE(n(SampleNodePtr).dataR);
  126.   DISPOSE(n);
  127. END FlushQueueFunc;
  128. (* \\\ ------------------------------------------------------------------------- *)
  129.  
  130. (* /// ---------------------- "PROCEDURE ReadExtension()" ---------------------- *)
  131. PROCEDURE ReadExtension * (size: LONGINT);
  132. BEGIN
  133.   IF size>0 THEN
  134.     ol.New(extendedData,size);
  135.     io.Read(extendedData,size);
  136.   ELSE
  137.     extendedData:=NIL;
  138.   END;
  139. END ReadExtension;
  140. (* \\\ ------------------------------------------------------------------------- *)
  141.  
  142. (* /// ----------------------- "PROCEDURE CloseAudio()" ------------------------ *)
  143. PROCEDURE CloseAudio();
  144.  
  145. VAR     cnt: INTEGER;
  146.  
  147. BEGIN
  148.   IF audioOpen THEN e.CloseDevice(mainIO); audioOpen:=FALSE; END;
  149.   IF mainIO#NIL THEN e.DeleteIORequest(mainIO); mainIO:=NIL; END;
  150.   IF mainPort#NIL THEN e.DeleteMsgPort(mainPort); mainPort:=NIL; END;
  151.   FOR cnt:=0 TO 1 DO
  152.     IF leftIO[cnt]#NIL THEN e.DeleteIORequest(leftIO[cnt]); leftIO[cnt]:=NIL; END;
  153.     IF rightIO[cnt]#NIL THEN e.DeleteIORequest(rightIO[cnt]); rightIO[cnt]:=NIL; END;
  154.     IF leftPort[cnt]#NIL THEN e.DeleteMsgPort(leftPort[cnt]); leftPort[cnt]:=NIL; END;
  155.     IF rightPort[cnt]#NIL THEN e.DeleteMsgPort(rightPort[cnt]); rightPort[cnt]:=NIL; END;
  156.   END;
  157. END CloseAudio;
  158. (* \\\ ------------------------------------------------------------------------- *)
  159.  
  160. (* /// ------------------------ "PROCEDURE OpenAudio()" ------------------------ *)
  161. PROCEDURE OpenAudio();
  162.  
  163. VAR     cnt: INTEGER;
  164.  
  165. BEGIN
  166.   playing:=FALSE;
  167.   bufPlaying[0]:=FALSE;
  168.   bufPlaying[1]:=FALSE;
  169.   currSample:=0;
  170.   es.NewList(sampleQueue);
  171.   mainPort:=e.CreateMsgPort();
  172.   IF mainPort=NIL THEN
  173.     d.PrintF("Can't create audio message port\n");
  174.     CloseAudio();
  175.   END;
  176.   mainIO:=e.CreateIORequest(mainPort,SIZE(mainIO^));
  177.   IF mainIO=NIL THEN
  178.     d.PrintF("Can't create audio iorequest\n");
  179.     CloseAudio();
  180.   END;
  181.  
  182.   FOR cnt:=0 TO 1 DO
  183.     leftPort[cnt]:=e.CreateMsgPort();
  184.     rightPort[cnt]:=e.CreateMsgPort();
  185.     IF (leftPort[cnt]=NIL) OR (rightPort[cnt]=NIL) THEN
  186.       d.PrintF("Can't create audio message port\n");
  187.       CloseAudio();
  188.     END;
  189.     leftIO[cnt]:=e.CreateIORequest(leftPort[cnt],SIZE(leftIO[cnt]^));
  190.     rightIO[cnt]:=e.CreateIORequest(rightPort[cnt],SIZE(rightIO[cnt]^));
  191.     IF (leftIO[cnt]=NIL) OR (rightIO[cnt]=NIL) THEN
  192.       d.PrintF("Can't create audio iorequest\n");
  193.       CloseAudio();
  194.     END;
  195.   END;
  196.   mainIO.request.message.node.pri:=au.allocMaxprec;
  197.   mainIO.data:=y.ADR(aus.channelMap);
  198.   mainIO.length:=aus.channelSize;
  199.   audioOpen:=(e.OpenDevice(au.audioName,0,mainIO,LONGSET{})=0);
  200.   IF ~audioOpen THEN
  201.     d.PrintF("Can't open audio.device!\n");
  202.     CloseAudio();
  203.   ELSE
  204.     aus.CopyUnit(mainIO,leftIO[0],aus.leftOnly);
  205.     aus.CopyUnit(mainIO,leftIO[1],aus.leftOnly);
  206.     aus.CopyUnit(mainIO,rightIO[0],aus.rightOnly);
  207.     aus.CopyUnit(mainIO,rightIO[1],aus.rightOnly);
  208.     aus.ResetAudio(mainIO);
  209.     aus.StopAudio(mainIO);
  210.   END;
  211. END OpenAudio;
  212. (* \\\ ------------------------------------------------------------------------- *)
  213.  
  214. (* /// ----------------------- "PROCEDURE PlaySample()" ------------------------ *)
  215. PROCEDURE PlaySample * (forceWait: BOOLEAN);
  216.  
  217. VAR     node: SampleNodePtr;
  218.         freq: LONGINT;
  219.         dataL: e.LSTRPTR;
  220.         dataR: e.LSTRPTR;
  221.         size: LONGINT;
  222.         offset: LONGINT;
  223.         reUse: BOOLEAN;
  224.  
  225. BEGIN
  226.   IF ~playing THEN RETURN; END;
  227.   IF bufPlaying[currSample] THEN
  228.     IF s.speedChanged THEN
  229.       IF e.CheckIO(leftIO[currSample])=NIL THEN e.AbortIO(leftIO[currSample]); END;
  230.       IF e.CheckIO(rightIO[currSample])=NIL THEN e.AbortIO(rightIO[currSample]); END;
  231.     ELSIF ~forceWait THEN
  232.       (* d.PrintF("check %ld\n",currSample); *)
  233.       IF (e.CheckIO(leftIO[currSample])=NIL) OR (e.CheckIO(rightIO[currSample])=NIL) THEN (* d.PrintF("still playing\n"); *) RETURN; END; (* Sample wird noch gespielt *)
  234.       (* d.PrintF("wait %ld\n",currSample); *)
  235.     END;
  236.     y.SETREG(0,e.WaitIO(leftIO[currSample]));
  237.     y.SETREG(0,e.WaitIO(rightIO[currSample]));
  238.   END;
  239.   node:=els.First(sampleQueue);
  240.   IF node#NIL THEN
  241.     freq:=node.freq;
  242.     size:=node.size;
  243.     offset:=node.done;
  244.     (* d.PrintF("rem: %08lx, %7ld, %7ld, %8ld\n",node,size,offset,node.id); *)
  245.     reUse:=FALSE;
  246.     IF size>maxAudioHWSize THEN
  247.       IF offset+maxAudioHWSize<size THEN
  248.         size:=maxAudioHWSize;
  249.         reUse:=TRUE;
  250.       ELSE
  251.         size:=size-offset;
  252.       END;
  253.     END;
  254.     dataL:=leftData[currSample];
  255.     e.CopyMemAPTR(y.ADR(node.dataL[offset]),dataL,size);
  256.     IF stereo THEN
  257.       dataR:=rightData[currSample];
  258.       e.CopyMemAPTR(y.ADR(node.dataR[offset]),dataR,size);
  259.     ELSE
  260.       dataR:=dataL;
  261.     END;
  262.     aus.WriteAudio(leftIO[currSample],dataL,size,freq,64);
  263.     aus.WriteAudio(rightIO[currSample],dataR,size,freq,64);
  264.     bufPlaying[currSample]:=TRUE;
  265.     currSample:=1-currSample;
  266.     audioSigs:=LONGSET{leftPort[currSample].sigBit,rightPort[currSample].sigBit};
  267.     IF reUse THEN
  268.       INC(node.done,maxAudioHWSize);
  269.     ELSIF mustPreload & o.doLoop THEN
  270.       node.done:=0;
  271.       y.SETREG(0,els.Dequeue(sampleQueue));
  272.       els.Enqueue(sampleQueue,node);
  273.     ELSE
  274.       y.SETREG(0,els.Dequeue(sampleQueue));
  275.       FlushQueueFunc(node);
  276.     END;
  277.   END;
  278. END PlaySample;
  279. (* \\\ ------------------------------------------------------------------------- *)
  280.  
  281. (* /// --------------------- "PROCEDURE Wait4LastSample()" --------------------- *)
  282. PROCEDURE Wait4LastSample * (aborted: BOOLEAN);
  283. BEGIN
  284.   IF ~aborted THEN
  285.     IF mustPreload & o.doLoop THEN
  286.       els.Flush(sampleQueue,FlushQueueFunc);
  287.     ELSE
  288.       WHILE ~es.ListEmpty(sampleQueue) DO PlaySample(~s.speedChanged); END;
  289.     END;
  290.   END;
  291. END Wait4LastSample;
  292. (* \\\ ------------------------------------------------------------------------- *)
  293.  
  294. (* /// ----------------------- "PROCEDURE StartSound()" ------------------------ *)
  295. PROCEDURE StartSound * ();
  296. BEGIN
  297.   IF ~playing THEN
  298.     playing:=TRUE;
  299.     IF ~bufPlaying[0] THEN PlaySample(FALSE); END;
  300.     IF bufPlaying[0] THEN
  301. (* /// "$IF RUNDEBUG" *)
  302.       IF o.debug THEN d.PrintF("starting audio\n"); END;
  303. (* \\\ $END *)
  304.       aus.StartAudio(mainIO);
  305.     ELSE
  306.       playing:=FALSE;
  307.     END;
  308.   END;
  309. END StartSound;
  310. (* \\\ ------------------------------------------------------------------------- *)
  311.  
  312. (* /// ------------------------ "PROCEDURE StopSound()" ------------------------ *)
  313. PROCEDURE StopSound * (aborted: BOOLEAN);
  314. BEGIN
  315.   (* IF es.ListEmpty(sampleQueue) THEN d.PrintF("empty\n"); END; *)
  316.   IF playing THEN
  317.     IF ~aborted & ~s.speedChanged THEN
  318.       y.SETREG(0,e.Wait(LONGSET{leftPort[1-currSample].sigBit}));
  319.       y.SETREG(0,e.Wait(LONGSET{rightPort[1-currSample].sigBit}));
  320.     END;
  321.     IF bufPlaying[1-currSample] THEN
  322.       WHILE e.CheckIO(leftIO[1-currSample])=NIL DO e.AbortIO(leftIO[1-currSample]); END;
  323.       y.SETREG(0,e.WaitIO(leftIO[1-currSample]));
  324.       WHILE e.CheckIO(rightIO[1-currSample])=NIL DO e.AbortIO(rightIO[1-currSample]); END;
  325.       y.SETREG(0,e.WaitIO(rightIO[1-currSample]));
  326.     END;
  327.     IF bufPlaying[currSample] THEN
  328.       WHILE e.CheckIO(leftIO[currSample])=NIL DO e.AbortIO(leftIO[currSample]); END;
  329.       y.SETREG(0,e.WaitIO(leftIO[currSample]));
  330.       WHILE e.CheckIO(rightIO[currSample])=NIL DO e.AbortIO(rightIO[currSample]); END;
  331.       y.SETREG(0,e.WaitIO(rightIO[currSample]));
  332.     END;
  333.     aus.StopAudio(mainIO);
  334.   END;
  335.   playing:=FALSE;
  336.   bufPlaying[0]:=FALSE;
  337.   bufPlaying[1]:=FALSE;
  338.   currSample:=0;
  339.   CloseAudio();
  340.   OpenAudio();
  341. END StopSound;
  342. (* \\\ ------------------------------------------------------------------------- *)
  343.  
  344. (* /// ----------------------- "PROCEDURE PauseSound()" ------------------------ *)
  345. PROCEDURE PauseSound * (pause: BOOLEAN);
  346. BEGIN
  347.   IF pause THEN
  348.     aus.StopAudio(mainIO);
  349.   ELSE
  350.     aus.StartAudio(mainIO);
  351.   END;
  352. END PauseSound;
  353. (* \\\ ------------------------------------------------------------------------- *)
  354.  
  355. (* /// ---------------------------- "TYPE PCMData" ----------------------------- *)
  356. TYPE    PCMDataPtr=UNTRACED POINTER TO PCMData;
  357.         PCMData=STRUCT (common: CommonData)
  358.         END;
  359.  
  360. VAR     pcmData: PCMDataPtr;
  361. (* \\\ ------------------------------------------------------------------------- *)
  362.  
  363. (* /// ----------------------- "PROCEDURE DecodePCM8()" ------------------------ *)
  364. PROCEDURE DecodePCM8Mono {"_DecodePCM8Mono"} (from{8}: e.APTR;
  365.                                               toL{9}: e.APTR;
  366.                                               toR{10}: e.APTR;
  367.                                               size{0}: LONGINT;
  368.                                               spec{11}: CommonDataPtr): LONGINT;
  369.  
  370. PROCEDURE DecodePCM8Stereo {"_DecodePCM8Stereo"} (from{8}: e.APTR;
  371.                                                   toL{9}: e.APTR;
  372.                                                   toR{10}: e.APTR;
  373.                                                   size{0}: LONGINT;
  374.                                                   spec{11}: CommonDataPtr): LONGINT;
  375.  
  376. PROCEDURE SetupPCM8(codec: CodecHeader);
  377. BEGIN
  378.   IF pcmData=NIL THEN NEW(pcmData); END;
  379.   IF codec.stereo THEN
  380.     decoderProc:=DecodePCM8Stereo;
  381.   ELSE
  382.     decoderProc:=DecodePCM8Mono;
  383.   END;
  384.   decoderSpec:=pcmData;
  385. END SetupPCM8;
  386. (* \\\ ------------------------------------------------------------------------- *)
  387.  
  388. (* /// ----------------------- "PROCEDURE DecodePCM16()" ----------------------- *)
  389. PROCEDURE DecodePCM16Mono {"_DecodePCM16Mono"} (from{8}: e.APTR;
  390.                                                 toL{9}: e.APTR;
  391.                                                 toR{10}: e.APTR;
  392.                                                 size{0}: LONGINT;
  393.                                                 spec{11}: CommonDataPtr): LONGINT;
  394.  
  395.  
  396. PROCEDURE DecodePCM16Stereo {"_DecodePCM16Stereo"} (from{8}: e.APTR;
  397.                                                     toL{9}: e.APTR;
  398.                                                     toR{10}: e.APTR;
  399.                                                     size{0}: LONGINT;
  400.                                                     spec{11}: CommonDataPtr): LONGINT;
  401.  
  402. PROCEDURE SetupPCM16(codec: CodecHeader);
  403. BEGIN
  404.   IF pcmData=NIL THEN NEW(pcmData); END;
  405.   IF codec.stereo THEN
  406.     decoderProc:=DecodePCM16Stereo;
  407.   ELSE
  408.     decoderProc:=DecodePCM16Mono;
  409.   END;
  410.   decoderSpec:=pcmData;
  411. END SetupPCM16;
  412. (* \\\ ------------------------------------------------------------------------- *)
  413.  
  414. (* /// -------------------------- "TYPE MSADPCMData" --------------------------- *)
  415. TYPE    MSADPCMDataPtr=UNTRACED POINTER TO MSADPCMData;
  416.         MSADPCMData=STRUCT (common: CommonData)
  417.             samplesPerBlock: INTEGER;
  418.         END;
  419.  
  420.         MSADPCMExtDataPtr=UNTRACED POINTER TO MSADPCMExtData;
  421.         MSADPCMExtData=STRUCT(dummy: ExtendedData)
  422.             samplesPerBlock: INTEGER;
  423.             numCoefs: INTEGER;
  424.         END;
  425.  
  426. VAR     msAdpcmData: MSADPCMDataPtr;
  427. (* \\\ ------------------------------------------------------------------------- *)
  428.  
  429. (* /// --------------------- "PROCEDURE DecodeMSADPCM4()" ---------------------- *)
  430. PROCEDURE DecodeMSADPCM4Mono {"_DecodeMSADPCM4Mono"} (from{8}: e.APTR;
  431.                                                       toL{9}: e.APTR;
  432.                                                       toR{10}: e.APTR;
  433.                                                       size{0}: LONGINT;
  434.                                                       spec{11}: CommonDataPtr): LONGINT;
  435.  
  436. PROCEDURE DecodeMSADPCM4Stereo {"_DecodeMSADPCM4Stereo"} (from{8}: e.APTR;
  437.                                                           toL{9}: e.APTR;
  438.                                                           toR{10}: e.APTR;
  439.                                                           size{0}: LONGINT;
  440.                                                           spec{11}: CommonDataPtr): LONGINT;
  441.  
  442. PROCEDURE SetupMSADPCM4(codec: CodecHeader);
  443. BEGIN
  444.   IF msAdpcmData=NIL THEN NEW(msAdpcmData); END;
  445.   IF (extendedData#NIL) & (g.animInfo.auds.strf.extSize>=2) THEN
  446.     msAdpcmData.samplesPerBlock:=i2m.LSB2MSBShort(extendedData(MSADPCMExtData).samplesPerBlock);
  447.   ELSE
  448.     d.PrintF("No extension data for MS ADPCM!\n");
  449.   END;
  450.   IF codec.stereo THEN
  451.     decoderProc:=DecodeMSADPCM4Stereo;
  452.   ELSE
  453.     decoderProc:=DecodeMSADPCM4Mono;
  454.   END;
  455.   decoderSpec:=msAdpcmData;
  456. END SetupMSADPCM4;
  457. (* \\\ ------------------------------------------------------------------------- *)
  458.  
  459. (* /// -------------------------- "TYPE DVIADPCMData" -------------------------- *)
  460. TYPE    DVIADPCMDataPtr=UNTRACED POINTER TO DVIADPCMData;
  461.         DVIADPCMData=STRUCT (common: CommonData)
  462.             blockCnt: INTEGER;
  463.         END;
  464.  
  465.         DVIADPCMExtDataPtr=UNTRACED POINTER TO DVIADPCMExtData;
  466.         DVIADPCMExtData=STRUCT(dummy: ExtendedData)
  467.             blockCnt: INTEGER;
  468.         END;
  469.  
  470. VAR     dviAdpcmData: DVIADPCMDataPtr;
  471. (* \\\ ------------------------------------------------------------------------- *)
  472.  
  473. (* /// --------------------- "PROCEDURE DecodeDVIADPCM4()" --------------------- *)
  474. PROCEDURE DecodeDVIADPCM4Mono {"_DecodeDVIADPCM4Mono"} (from{8}: e.APTR;
  475.                                                         toL{9}: e.APTR;
  476.                                                         toR{10}: e.APTR;
  477.                                                         size{0}: LONGINT;
  478.                                                         spec{11}: CommonDataPtr): LONGINT;
  479.  
  480. PROCEDURE DecodeDVIADPCM4Stereo {"_DecodeDVIADPCM4Stereo"} (from{8}: e.APTR;
  481.                                                             toL{9}: e.APTR;
  482.                                                             toR{10}: e.APTR;
  483.                                                             size{0}: LONGINT;
  484.                                                             spec{11}: CommonDataPtr): LONGINT;
  485.  
  486. PROCEDURE SetupDVIADPCM4(codec: CodecHeader);
  487. BEGIN
  488.   IF dviAdpcmData=NIL THEN NEW(dviAdpcmData); END;
  489.   IF (extendedData#NIL) & (g.animInfo.auds.strf.extSize>=2) THEN
  490.     dviAdpcmData.blockCnt:=i2m.LSB2MSBShort(extendedData(DVIADPCMExtData).blockCnt);
  491.   ELSE
  492.     d.PrintF("No extension data for DVI ADPCM!\n");
  493.   END;
  494.   IF codec.stereo THEN
  495.     decoderProc:=DecodeDVIADPCM4Stereo;
  496.   ELSE
  497.     decoderProc:=DecodeDVIADPCM4Mono;
  498.   END;
  499.   decoderSpec:=dviAdpcmData;
  500. END SetupDVIADPCM4;
  501. (* \\\ ------------------------------------------------------------------------- *)
  502.  
  503. (* /// ----------------------- "PROCEDURE CodecQuery()" ------------------------ *)
  504. PROCEDURE CodecQuery * (VAR codec: CodecHeader): LONGINT;
  505.  
  506. VAR     ret: LONGINT;
  507.  
  508. BEGIN
  509.   ret:=codecSupported;
  510.   codec.stereo:=(codec.channels>1);
  511.   CASE codec.compression OF
  512.   | wavePCM:
  513.       codec.description:="PCM";
  514.       codec.compFactor:=1;
  515.       IF codec.bits=8 THEN
  516.         SetupPCM8(codec);
  517.       ELSIF codec.bits=16 THEN
  518.         SetupPCM16(codec);
  519.       ELSE
  520.         ret:=codecUnsupported;
  521.       END;
  522.   | waveMsADPCM:
  523.       codec.description:="Microsoft ADPCM";
  524.       codec.compFactor:=2;
  525.       IF codec.bits=4 THEN
  526.         SetupMSADPCM4(codec);
  527.       ELSE
  528.         ret:=codecUnsupported;
  529.       END;
  530.   | waveDviADPCM:
  531.       codec.description:="DVI ADPCM";
  532.       codec.compFactor:=2;
  533.       IF codec.bits=4 THEN
  534.         SetupDVIADPCM4(codec);
  535.       ELSE
  536.         ret:=codecUnsupported;
  537.       END;
  538.   | waveIBMCVSD:
  539.       codec.description:="IBM CVSD";
  540.       ret:=codecUnsupported;
  541.   | waveALAW:
  542.       codec.description:="a-Law";
  543.       ret:=codecUnsupported;
  544.   | waveMULAW:
  545.       codec.description:="µ-Law";
  546.       ret:=codecUnsupported;
  547.   | waveOkiADPCM:
  548.       codec.description:="Oki ADPCM";
  549.       ret:=codecUnsupported;
  550.   | waveYamahaADPCM:
  551.       codec.description:="Yamaha ADPCM";
  552.       ret:=codecUnsupported;
  553.   | waveDSPTrueSpeech:
  554.       codec.description:="DSP TrueSpeech";
  555.       ret:=codecUnsupported;
  556.   | waveMsGSM610:
  557.       codec.description:="Microsoft GSM610";
  558.       ret:=codecUnsupported;
  559.   | ibmMULAW:
  560.       codec.description:="IBM µ-Law";
  561.       ret:=codecUnsupported;
  562.   | ibmALAW:
  563.       codec.description:="IBM a-Law";
  564.       ret:=codecUnsupported;
  565.   | ibmADPCM:
  566.       codec.description:="IBM ADPCM";
  567.       ret:=codecUnsupported;
  568.   ELSE
  569.     codec.description:="unknown";
  570.     ret:=codecUnknown;
  571.   END;
  572.   RETURN ret;
  573. END CodecQuery;
  574. (* \\\ ------------------------------------------------------------------------- *)
  575.  
  576. (* /// ---------------------- "PROCEDURE CheckAudioDMA()" ---------------------- *)
  577. PROCEDURE CheckAudioDMA(freq: LONGINT): LONGINT;
  578. BEGIN
  579.   IF (freq>27000) & ~v.doubleScanned THEN
  580.     decoderSpec.downScale:=TRUE;
  581.     freq:=freq DIV 2;
  582.   ELSE
  583.     decoderSpec.downScale:=FALSE;
  584.   END;
  585.   RETURN freq;
  586. END CheckAudioDMA;
  587. (* \\\ ------------------------------------------------------------------------- *)
  588.  
  589. (* /// ----------------------- "PROCEDURE DecodeFrame()" ----------------------- *)
  590. PROCEDURE DecodeFrame * (size: LONGINT);
  591.  
  592. VAR     node: SampleNodePtr;
  593.         decSize: LONGINT;
  594.  
  595. BEGIN
  596.   IF audioFreq=-1 THEN audioFreq:=CheckAudioDMA(g.animInfo.auds.strf.samplesPerSec); END;
  597.   IF size>1 THEN
  598.     io.Read(mainData,size);
  599.     NEW(node);
  600.     decSize:=i2m.Round(size*audioSizeScale,e.blockSize);
  601.     ol.New(node.dataL,decSize);
  602.     IF stereo THEN ol.New(node.dataR,decSize); END;
  603.     decSize:=decoderProc(mainData,node.dataL,node.dataR,size,decoderSpec);
  604.     node.freq:=audioFreq;
  605.     node.size:=decSize;
  606.     node.done:=0;
  607.     (* node.id:=u.GetUniqueID(); *)
  608.     els.Enqueue(sampleQueue,node);
  609.   END;
  610. END DecodeFrame;
  611. (* \\\ ------------------------------------------------------------------------- *)
  612.  
  613. (* /// ------------------------- "PROCEDURE Preload()" ------------------------- *)
  614. PROCEDURE Preload * (offset: LONGINT;
  615.                      size: LONGINT);
  616. BEGIN
  617. (* /// "$IF RUNDEBUG" *)
  618.   IF o.debug THEN d.PrintF("preload single audio frame (offset: %ld, size: %ld)\n",offset,size); END;
  619. (* \\\ $END *)
  620.   io.SeekTo(offset);
  621.   DecodeFrame(size);
  622. END Preload;
  623. (* \\\ ------------------------------------------------------------------------- *)
  624.  
  625. (* /// ---------------------- "PROCEDURE AllocBuffers()" ----------------------- *)
  626. PROCEDURE AllocBuffers * (): BOOLEAN;
  627.  
  628. VAR     codec: CodecHeader;
  629.         cnt: INTEGER;
  630.         ret: BOOLEAN;
  631.         round: LONGINT;
  632.         samplesPerSec: LONGINT;
  633.         bytesPerSec: LONGINT;
  634.         fps: LONGINT;
  635.  
  636. BEGIN
  637.   ret:=TRUE;
  638.   codec.compression:=g.animInfo.auds.strf.format;
  639.   codec.bits:=g.animInfo.auds.strf.bitsPerSample;
  640.   codec.channels:=g.animInfo.auds.strf.channels;
  641.   codec.extSize:=g.animInfo.auds.strf.extSize;
  642.   CASE CodecQuery(codec) OF
  643.   | codecUnsupported:
  644.       d.PrintF("  Unsupported audio encoding: %s, %ld bits, %ld channels\n",y.ADR(codec.description),
  645.                                                                             codec.bits,
  646.                                                                             codec.channels);
  647.       IF ~o.noSound THEN d.PrintF("Continuing without sound\n"); END;
  648.       ret:=FALSE;
  649.   | codecUnknown:
  650.       d.PrintF("  Unknown audio encoding: $%08lx, %ld bits, %ld channels\n",codec.compression,
  651.                                                                             codec.bits,
  652.                                                                             codec.channels);
  653.       IF ~o.noSound THEN d.PrintF("Continuing without sound\n"); END;
  654.       ret:=FALSE;
  655.   ELSE
  656.     IF ~o.quiet THEN
  657.       IF codec.stereo THEN
  658.         d.PrintF("  Audio: %s %ld bit Stereo, %lD Hz\n",y.ADR(codec.description),
  659.                                                         codec.bits,
  660.                                                         g.animInfo.auds.strf.samplesPerSec);
  661.       ELSE
  662.         d.PrintF("  Audio: %s %ld bit Mono, %lD Hz\n",y.ADR(codec.description),
  663.                                                       codec.bits,
  664.                                                       g.animInfo.auds.strf.samplesPerSec);
  665.       END;
  666.     END;
  667.     IF ~o.noSound THEN (* soll überhaupt was gespielt werden?? *)
  668.       stereo:=codec.stereo;
  669.       IF ~(8 IN g.animInfo.avih.flags) & (g.animInfo.avih.initialFrames=0) & (g.animInfo.auds.strh.length#0) & (g.animInfo.auds.strh.suggestedBufferSize=0) THEN
  670.         bytesPerSec:=g.animInfo.auds.strh.length*g.animInfo.auds.strh.sampleSize; (* früher *....scale *)
  671.         samplesPerSec:=mu.min(bytesPerSec,maxAudioHWSize);
  672.         mustPreload:=TRUE;
  673.       ELSE
  674.         bytesPerSec:=g.animInfo.auds.strf.avgBytesPerSec;
  675.         samplesPerSec:=g.animInfo.auds.strf.samplesPerSec;
  676.         mustPreload:=FALSE;
  677.       END;
  678.       round:=mu.max(g.animInfo.auds.strf.blockAlign,64); (* 8 reicht nicht immer *)
  679.       bytesPerSec:=i2m.Round(bytesPerSec,round);
  680.       samplesPerSec:=i2m.Round(samplesPerSec,round);
  681.       IF codec.compFactor#1 THEN samplesPerSec:=mu.max(samplesPerSec,bytesPerSec*codec.compFactor); END;
  682.       DISPOSE(mainData);
  683.       ol.New(mainData,bytesPerSec); (* Speicher für eine Sekunde allokieren *)
  684.       INCL(ol.MemReqs,e.chip);
  685.       FOR cnt:=0 TO 1 DO
  686.         DISPOSE(leftData[cnt]);
  687.         DISPOSE(rightData[cnt]);
  688.         ol.New(leftData[cnt],samplesPerSec);
  689.         IF stereo THEN ol.New(rightData[cnt],samplesPerSec); END;
  690.       END;
  691.       EXCL(ol.MemReqs,e.chip);
  692.       audioFreq:=-1;
  693.       audioBufferSize:=mu.min(bytesPerSec,maxAudioHWSize);
  694.       audioSigs:=LONGSET{};
  695.       audioSizeScale:=codec.compFactor;
  696.     END;
  697.   END;
  698.   es.NewList(sampleQueue);
  699.   RETURN ret;
  700. END AllocBuffers;
  701. (* \\\ ------------------------------------------------------------------------- *)
  702.  
  703. BEGIN
  704.   OpenAudio();
  705. CLOSE
  706.   CloseAudio();
  707. END CyberAVIAudio.
  708.